with v8.Class_Value, v8.Class_String, v8.Class_Object;
with v8.Class_Object_Template;
with v8.Generic_Handles;
package v8.Class_Context is
   type Context (<>) is tagged limited private;
   type Pointer is access all Context;
   -- A sandboxed execution context with its own set of built-in objects
   -- and functions.

   package Handles is new v8.Generic_Handles(Pointer);

   function Global (this : Context) return v8.Class_Object.Pointer;
   -- Returns the global proxy object or global object itself for
   -- detached contexts.
   --
   -- Global proxy object is a thin wrapper whose prototype points to
   -- actual context's global object with the properties like Object, etc.
   -- This is done that way for security reasons (for more details see
   -- https://wiki.mozilla.org/Gecko:SplitWindow).
   --
   -- Please note that changes to global proxy object prototype most probably
   -- would break VM---v8 expects only global object as a prototype of
   -- global proxy object.
   --
   -- If Detach_Global has been invoked, Global would return actual global
   -- object until global is reattached with Reattach_Global.

   procedure Detach_Global (this : in out Context);
   -- Detaches the global object from its context before
   -- the global object can be reused to create a new context.

   procedure Reattach_Global
     (this          : in out Context;
      global_object : v8.Class_Object.Pointer);
   -- Reattaches a global object to a context.  This can be used to
   -- restore the connection between a global object and a context
   -- after DetachGlobal has been called.
   --
   -- \param global_object The global object to reattach to the
   --   context.  For this to work, the global object must be the global
   --   object that was associated with this context before a call to
   --   DetachGlobal.



   procedure Set_Security_Token
     (this  : in out Context;
      token : v8.Class_Value.Pointer);
   -- Sets the security token for the context.  To access an object in
   -- another context, the security tokens must match.
   -- token => Handle<Value>

   procedure Use_Default_Security_Token (this : in out Context);
   -- Restores the security token to the default value.

   function Get_Security_Token (this : Context) return v8.Class_Value.Pointer;
   -- Returns the security token of this context.
   -- return Handle<Value>

   procedure Enter (this : in out Context);
   -- Enter this context.  After entering a context, all code compiled
   -- and run is compiled and run in this context.  If another context
   -- is already entered, this old context is saved so it can be
   -- restored when the new context is exited.

   procedure Leave (this : in out Context);
   -- Exit this context.  Exiting the current context restores the
   -- context that was in place when entering the current context.

   function Has_Out_Of_Memory_Exception (this : Context) return bool;
   -- Returns true if the context has experienced an out of memory situation.

   procedure Set_Data (this : in out Context; data : v8.Class_String.Pointer);
   function Get_Data (this : Context) return v8.Class_String.Pointer;
   -- Associate an additional data object with the context. This is mainly used
   -- with the debugger to provide additional information on the context through
   -- the debugger API.

   procedure Allow_Code_Generation_From_Strings (this : in out Context; allow : bool);
   -- Control whether code generation from strings is allowed. Calling
   -- this method with false will disable 'eval' and the 'Function'
   -- constructor for code running in this context. If 'eval' or the
   -- 'Function' constructor are used an exception will be thrown.
   --
   -- If code generation from strings is not allowed the
   -- V8::AllowCodeGenerationFromStrings callback will be invoked if
   -- set before blocking the call to 'eval' or the 'Function'
   -- constructor. If that callback returns true, the call will be
   -- allowed, otherwise an exception will be thrown. If no callback is
   -- set an exception will be thrown.

   function Create
     (extensions      : access Extension_Configuration := null;
      global_template : v8.Class_Object_Template.Pointer := null;
      global_object   : v8.Class_Value.Pointer := null
     ) return Handles.Persistent;
   -- Creates a new context.
   --
   -- Returns a persistent handle to the newly allocated context. This
   -- persistent handle has to be disposed when the context is no
   -- longer used so the context can be garbage collected.
   --
   -- \param extensions An optional extension configuration containing
   -- the extensions to be installed in the newly created context.
   --
   -- \param global_template An optional object template from which the
   -- global object for the newly created context will be created.
   --
   -- \param global_object An optional global object to be reused for
   -- the newly created context. This global object must have been
   -- created by a previous call to Context::New with the same global
   -- template. The state of the global object will be completely reset
   -- and only object identify will remain.
   -- return Persistent<Context>

   function Get_Entered return Pointer;
   -- Returns the last entered context.
   -- return Local<Context>

   function Get_Current return Pointer;
   -- Returns the context that is on the top of the stack.
   -- return Local<Context>

   function Get_Calling return Pointer;
   -- Returns the context of the calling JavaScript code.  That is the
   -- context of the top-most JavaScript frame.  If there are no
   -- JavaScript frames an empty handle is returned.
   -- return Local<Context>

   function In_Context return bool;
   -- Returns true if V8 has a current context.

   type Scope (owner : access Context) is limited private;
   -- provide convenient to auto enter / leave

private
   type Context is tagged limited null record;

   pragma No_Strict_Aliasing (Pointer);

   type Scope (owner : access Context) is new Ada.Finalization.Limited_Controlled with null record;
   procedure Initialize (this : in out Scope);
   procedure Finalize(this : in out Scope);

   pragma Import (CPP, Global, "_ZN2v87Context6GlobalEv");
   pragma Import (CPP, Detach_Global, "_ZN2v87Context12DetachGlobalEv");
   pragma Import (CPP, Create, "_ZN2v87Context3NewEPNS_22ExtensionConfigurationENS_6HandleINS_14ObjectTemplateEEENS3_INS_5ValueEEE");
   pragma Import (CPP, Reattach_Global, "_ZN2v87Context14ReattachGlobalENS_6HandleINS_6ObjectEEE");
   pragma Import (CPP, Get_Entered, "_ZN2v87Context10GetEnteredEv");
   pragma Import (CPP, Get_Current, "_ZN2v87Context10GetCurrentEv");
   pragma Import (CPP, Get_Calling, "_ZN2v87Context10GetCallingEv");
   pragma Import (CPP, Set_Security_Token, "_ZN2v87Context16SetSecurityTokenENS_6HandleINS_5ValueEEE");
   pragma Import (CPP, Use_Default_Security_Token, "_ZN2v87Context23UseDefaultSecurityTokenEv");
   pragma Import (CPP, Get_Security_Token, "_ZN2v87Context16GetSecurityTokenEv");
   pragma Import (CPP, Enter, "_ZN2v87Context5EnterEv");
   pragma Import (CPP, Leave, "_ZN2v87Context4ExitEv");
   pragma Import (CPP, Has_Out_Of_Memory_Exception, "_ZN2v87Context23HasOutOfMemoryExceptionEv");
   pragma Import (CPP, In_Context, "_ZN2v87Context9InContextEv");
   pragma Import (CPP, Set_Data, "_ZN2v87Context7SetDataENS_6HandleINS_6StringEEE");
   pragma Import (CPP, Get_Data, "_ZN2v87Context7GetDataEv");
   pragma Import (CPP, Allow_Code_Generation_From_Strings, "_ZN2v87Context30AllowCodeGenerationFromStringsEb");

end v8.Class_Context;
